import 'dart:convert';
import 'dart:developer';

import 'package:largefriends/entity/entities/lf_album_entity.dart';
import 'package:largefriends/entity/entities/lf_bool_entity.dart';
import 'package:largefriends/entity/entities/lf_city_entity.dart';
import 'package:largefriends/entity/entities/lf_limit_entity.dart';
import 'package:largefriends/entity/entities/lf_matchage_entity.dart';
import 'package:largefriends/entity/entities/lf_relation_result_entity.dart';
import 'package:largefriends/entity/entities/lf_site_key_entity.dart';
import 'package:largefriends/entity/entities/lf_token_entity.dart';
import 'package:largefriends/entity/entities/type_config_list.dart';
import 'package:largefriends/entity/entities/verify_email_entity.dart';

import '../../utils/lf_logger.dart';
import '../entities/chat_new_message_entity.dart';
import '../entities/lf_attachment_entity.dart';
import '../entities/lf_badge_entity.dart';
import '../entities/lf_chat_can_message.dart';
import '../entities/lf_gesture_entity.dart';
import '../entities/lf_location_entity.dart';
import '../entities/lf_notification_status_entity.dart';
import '../entities/lf_photo_entity.dart';
import '../entities/lf_user_entity.dart';
import '../entities/lf_wink_entity.dart';
import '../entities/type_config_list_entity.dart';

void tryCatch(Function? f) {
  try {
    f?.call();
  } catch (e, stack) {
    log('$e');
    log('$stack');
  }
}

class FFConvert {
  FFConvert._();

  static T? convert<T extends Object?>(dynamic value) {
    if (value == null) {
      return null;
    }

    String typeStr = T.toString();
    // lfLogger.w(typeStr);
    if (value is List) {
      return generateOBJList<T>(typeStr, value);
    }
    return _generateItemOBJ(typeStr, value) as T;
  }
}

M _generateItemOBJ<M>(String typeStr, dynamic jsonObj) {
  late dynamic obj;
  switch (typeStr) {
    case 'LfUserEntity':
      obj = LfUserEntity.fromJson(jsonObj);
      break;
    case 'LfCityEntity':
      obj = LfCityEntity.fromJson(jsonObj);
      break;
    case 'LfNotificationStatusEntity':
      obj = LfNotificationStatusEntity.fromJson(jsonObj);
      break;
    case 'LfLocationEntity':
      obj = LfLocationEntity.fromJson(jsonObj);
      break;
    case 'LfSiteKeyEntity':
      obj = LfSiteKeyEntity.fromJson(jsonObj);
      break;
    case 'LfAttachmentEntity':
      obj = LfAttachmentEntity.fromJson(jsonObj);
      break;
    case 'LfTokenEntity':
      obj = LfTokenEntity.fromJson(jsonObj);
      break;
    case 'LfBoolEntity':
      obj = LfBoolEntity.fromJson(jsonObj);
      break;
    case 'LfMatchAgeEntity':
      obj = LfMatchAgeEntity.fromJson(jsonObj);
      break;
    case 'LfPhotoEntity':
      obj = LfPhotoEntity.fromJson(jsonObj);
      break;
    case 'ChatNewMessageEntity':
      obj = ChatNewMessageEntity.fromJson(jsonObj);
      break;
    case 'LfChatCanMessage':
      obj = LfChatCanMessage.fromJson(jsonObj);
      break;
    case 'TypeConfigListEntity':
      obj = TypeConfigListEntity.fromJson(jsonObj);
      break;
    case 'TypeConfigEntity':
      obj = TypeConfigEntity.fromJson(jsonObj);
      break;
    case 'LfAlbumEntity':
      obj = LfAlbumEntity.fromJson(jsonObj);
      break;
    case 'LfBadgeEntity':
      obj = LfBadgeEntity.fromJson(jsonObj);
      break;
    case 'LfWinkEntity':
      obj = LfWinkEntity.fromJson(jsonObj);
      break;
    case 'VerifyEmailEntity':
      obj = VerifyEmailEntity.fromJson(jsonObj);
      break;
    case 'LfGestureEntity':
      obj = LfGestureEntity.fromJson(jsonObj);
      break;
    case 'TypeConfigList':
      obj = TypeConfigList.fromJson(jsonObj);
      break;
    case 'LfLimitEntity':
      obj = LfLimitEntity.fromJson(jsonObj);
      break;
    case 'LfRelationResultEntity':
      obj = LfRelationResultEntity.fromJson(jsonObj);
      break;
    case 'XInfo':
      obj = XInfo.fromJson(jsonObj);
      break;
    case 'String':
      obj = json.decode(jsonObj) as String;
      break;
    default:
      lfLogger.e('json parse error');
      obj = jsonObj;
      break;
  }
  return obj as M;
}

T generateOBJList<T>(String typeStr, List data) {
  typeStr = typeStr.substring(5, typeStr.length - 1);
  List list;
  switch (typeStr) {
    case 'LfUserEntity':
      list = data
          .map<LfUserEntity>((e) => _generateItemOBJ<LfUserEntity>(typeStr, e))
          .toList();
      break;
    case 'LfCityEntity':
      list = data
          .map<LfCityEntity>((e) => _generateItemOBJ<LfCityEntity>(typeStr, e))
          .toList();
      break;
    case 'LfNotificationStatusEntity':
      list = data
          .map<LfNotificationStatusEntity>(
              (e) => _generateItemOBJ<LfNotificationStatusEntity>(typeStr, e))
          .toList();
      break;
    case 'LfLocationEntity':
      list = data
          .map<LfLocationEntity>(
              (e) => _generateItemOBJ<LfLocationEntity>(typeStr, e))
          .toList();
      break;
    case 'LfAttachmentEntity':
      list = data
          .map<LfAttachmentEntity>(
              (e) => _generateItemOBJ<LfAttachmentEntity>(typeStr, e))
          .toList();
      break;
    case 'LfTokenEntity':
      list = data
          .map<LfTokenEntity>(
              (e) => _generateItemOBJ<LfTokenEntity>(typeStr, e))
          .toList();
      break;
    case 'TypeConfigListEntity':
      list = data
          .map<TypeConfigListEntity>(
              (e) => _generateItemOBJ<TypeConfigListEntity>(typeStr, e))
          .toList();
      break;
    case 'TypeConfigEntity':
      list = data
          .map<TypeConfigEntity>(
              (e) => _generateItemOBJ<TypeConfigEntity>(typeStr, e))
          .toList();
      break;
    case 'LfBoolEntity':
      list = data
          .map<LfBoolEntity>((e) => _generateItemOBJ<LfBoolEntity>(typeStr, e))
          .toList();
      break;
    case 'LfMatchAgeEntity':
      list = data
          .map<LfMatchAgeEntity>(
              (e) => _generateItemOBJ<LfMatchAgeEntity>(typeStr, e))
          .toList();
      break;
    case 'LfPhotoEntity':
      list = data
          .map<LfPhotoEntity>(
              (e) => _generateItemOBJ<LfPhotoEntity>(typeStr, e))
          .toList();
      break;
    // case 'ChatUserEntity':
    //   list = data
    //       .map<ChatUserEntity>(
    //           (e) => _generateItemOBJ<ChatUserEntity>(typeStr, e))
    //       .toList();
    //   break;
    case 'ChatNewMessageEntity':
      list = data
          .map<ChatNewMessageEntity>(
              (e) => _generateItemOBJ<ChatNewMessageEntity>(typeStr, e))
          .toList();
      break;
    case 'LfChatCanMessage':
      list = data
          .map<LfChatCanMessage>(
              (e) => _generateItemOBJ<LfChatCanMessage>(typeStr, e))
          .toList();
      break;
    case 'LfAlbumEntity':
      list = data
          .map<LfAlbumEntity>(
              (e) => _generateItemOBJ<LfAlbumEntity>(typeStr, e))
          .toList();
      break;
    case 'LfBadgeEntity':
      list = data
          .map<LfBadgeEntity>(
              (e) => _generateItemOBJ<LfBadgeEntity>(typeStr, e))
          .toList();
      break;
    case 'LfWinkEntity':
      list = data
          .map<LfWinkEntity>((e) => _generateItemOBJ<LfWinkEntity>(typeStr, e))
          .toList();
      break;
    case 'VerifyEmailEntity':
      list = data
          .map<VerifyEmailEntity>(
              (e) => _generateItemOBJ<VerifyEmailEntity>(typeStr, e))
          .toList();
      break;
    case 'LfGestureEntity':
      list = data
          .map<LfGestureEntity>(
              (e) => _generateItemOBJ<LfGestureEntity>(typeStr, e))
          .toList();
      break;
    case 'TypeConfigList':
      list = data
          .map<TypeConfigList>(
              (e) => _generateItemOBJ<TypeConfigList>(typeStr, e))
          .toList();
      break;
    case 'LfLimitEntity':
      list = data
          .map<LfLimitEntity>(
              (e) => _generateItemOBJ<LfLimitEntity>(typeStr, e))
          .toList();
      break;
    case 'LfRelationResultEntity':
      list = data
          .map<LfRelationResultEntity>(
              (e) => _generateItemOBJ<LfRelationResultEntity>(typeStr, e))
          .toList();
      break;
    case 'XInfo':
      list =
          data.map<XInfo>((e) => _generateItemOBJ<XInfo>(typeStr, e)).toList();
      break;
    case 'String':
      list = data
          .map<String>((e) => _generateItemOBJ<String>(typeStr, e))
          .toList();
      break;
    default:
      lfLogger.e("failed decode $typeStr");
      if (data.isNotEmpty && data.first is List) {
        list = data.map((e) => generateOBJList<List>(typeStr, e)).toList();
      } else {
        list = data.map((e) => _generateItemOBJ(typeStr, e)).toList();
      }
      break;
  }
  return list as T;
}
